/*
 * Copyright (c) 2014, KJFrameForAndroid 张涛 (kymjs123@gmail.com).
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.kymjs.aframe.ui.activity;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.ActionBar;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.StrictMode;
import android.provider.Settings;
import android.support.annotation.NonNull;
import android.support.v4.content.PermissionChecker;
import android.view.KeyEvent;
import android.view.Window;
import android.view.WindowManager;

import com.jason.fingerprint.R;
import com.jason.fingerprint.utils.SystemUtils;

import org.kymjs.aframe.KJLoger;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import de.greenrobot.event.EventBus;
import de.greenrobot.event.Subscribe;
import permissions.dispatcher.NeedsPermission;
import permissions.dispatcher.OnNeverAskAgain;
import permissions.dispatcher.OnPermissionDenied;
import permissions.dispatcher.RuntimePermissions;

/**
 * Application BaseActivity,you should inherit it for your Activity<br>
 * <p>
 * <b>创建时间</b> 2014-5-28
 *
 * @author kymjs(kymjs123@gmail.com)
 * @version 1.2
 */
@RuntimePermissions
public abstract class BaseActivity extends KJFrameActivity {

    public static final int FLAG_HOMEKEY_DISPATCHED = 0x80000000; //需要自己定义标志

    /**
     * 当前Activity状态
     */
    public enum ActivityState {
        RESUME, PAUSE, STOP, DESTROY
    }

    /**
     * Activity显示方向
     */
    public enum ScreenOrientation {
        HORIZONTAL, VERTICAL, AUTO
    }

    public Activity aty;
    /**
     * Activity状态
     */
    public ActivityState activityState = ActivityState.DESTROY;
    // 是否允许全屏
    private boolean mAllowFullScreen = false;
    // 是否隐藏ActionBar
    private boolean mHiddenActionBar = true;
    // 是否启用框架的退出界面
    private boolean mOpenBackListener = false;

    // 屏幕方向
    private ScreenOrientation orientation = ScreenOrientation.VERTICAL;

    /**
     * 是否全屏显示本Activity，全屏后将隐藏状态栏，默认不全屏（若修改必须在构造方法中调用）
     *
     * @param allowFullScreen 是否允许全屏
     */
    public void setAllowFullScreen(boolean allowFullScreen) {
        this.mAllowFullScreen = allowFullScreen;
    }

    /**
     * 是否隐藏ActionBar，默认隐藏（若修改必须在构造方法中调用）
     *
     * @param hiddenActionBar 是否隐藏ActionBar
     */
    public void setHiddenActionBar(boolean hiddenActionBar) {
        this.mHiddenActionBar = hiddenActionBar;
    }

    /**
     * 修改屏幕显示方向，默认竖屏锁定（若修改必须在构造方法中调用）
     *
     * @param orientation
     */
    public void setScreenOrientation(ScreenOrientation orientation) {
        this.orientation = orientation;
    }

    /**
     * 是否启用返回键监听，若启用，则在显示最后一个Activity时将弹出退出对话框。默认启用（若修改必须在构造方法中调用）
     *
     * @param openBackListener
     */
    public void setBackListener(boolean openBackListener) {
        this.mOpenBackListener = openBackListener;
    }

    /**
     * @return 返回是否启用返回键监听
     */
    protected boolean getBackListener() {
        return this.mOpenBackListener;
    }

    /**
     * skip to @param(cls)，and call @param(aty's) finish() method
     */
    @Override
    public void skipActivity(Activity aty, Class<?> cls) {
        showActivity(aty, cls);
        aty.finish();
    }

    /**
     * skip to @param(cls)，and call @param(aty's) finish() method
     */
    @Override
    public void skipActivity(Activity aty, Intent it) {
        showActivity(aty, it);
        aty.finish();
    }

    /**
     * skip to @param(cls)，and call @param(aty's) finish() method
     */
    @Override
    public void skipActivity(Activity aty, Class<?> cls, Bundle extras) {
        showActivity(aty, cls, extras);
        aty.finish();
    }

    /**
     * show to @param(cls)，but can't finish activity
     */
    @Override
    public void showActivity(Activity aty, Class<?> cls) {
        Intent intent = new Intent();
        intent.setClass(aty, cls);
        aty.startActivity(intent);
    }

    /**
     * show to @param(cls)，but can't finish activity
     */
    @Override
    public void showActivity(Activity aty, Intent it) {
        aty.startActivity(it);
    }

    /**
     * show to @param(cls)，but can't finish activity
     */
    @Override
    public void showActivity(Activity aty, Class<?> cls, Bundle extras) {
        Intent intent = new Intent();
        intent.putExtras(extras);
        intent.setClass(aty, cls);
        aty.startActivity(intent);
    }

    /***************************************************************************
     *
     * print Activity callback methods
     *
     ***************************************************************************/
    @Override
    protected void onCreate(Bundle savedInstanceState) {
//        this.getWindow().setFlags(FLAG_HOMEKEY_DISPATCHED, FLAG_HOMEKEY_DISPATCHED);
        aty = this;
        KJLoger.state(this.getClass().getName(), "---------onCreat ");
        switch (orientation) {
            case HORIZONTAL:
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
                break;
            case VERTICAL:
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                break;
            case AUTO:
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER);
                break;
        }

        if (mHiddenActionBar) {
            requestWindowFeature(Window.FEATURE_NO_TITLE);
        } else {
            ActionBar a = getActionBar();
            if (a != null){
                a.show();
            }
        }
        if (mAllowFullScreen) {
            getWindow().setFlags(
                    WindowManager.LayoutParams.FLAG_FULLSCREEN,
                    WindowManager.LayoutParams.FLAG_FULLSCREEN);
        }
        super.onCreate(savedInstanceState);
        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
                .detectAll()
                .penaltyLog()
                .penaltyDialog()
                .detectDiskReads()
                .detectDiskWrites()
                .detectNetwork().permitAll().build();
        StrictMode.setThreadPolicy(policy);
        EventBus.getDefault().register(this);
    }

    @Subscribe
    public void onEvent(String event) {
        onEventCallBack(event);
    }

    protected void onEventCallBack(String event) {
    }


    @Override
    protected void onStart() {
        super.onStart();
        KJLoger.state(this.getClass().getName(), "---------onStart ");
    }

    @Override
    protected void onResume() {
        super.onResume();
        activityState = ActivityState.RESUME;
        KJLoger.state(this.getClass().getName(), "---------onResume ");
    }

    @Override
    protected void onPause() {
        super.onPause();
        activityState = ActivityState.PAUSE;
        KJLoger.state(this.getClass().getName(), "---------onPause ");
    }

    @SuppressLint("MissingSuperCall")
    @Override
    protected void onStop() {
        super.onResume();
        activityState = ActivityState.STOP;
        KJLoger.state(this.getClass().getName(), "---------onStop ");
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        KJLoger.state(this.getClass().getName(),
                "---------onRestart ");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        EventBus.getDefault().unregister(this);
        activityState = ActivityState.DESTROY;
        KJLoger.state(this.getClass().getName(),
                "---------onDestroy ");
    }

    private PermissionHandler mPermissionHandler;

    /***
     * 权限回调接口
     */
    public abstract class PermissionHandler {

        //权限通过
        public abstract void onGranted();

        //权限拒绝
        public void onDenied() {

        }
    }

    /**
     * 请求相机权限
     *
     * @param permissionHandler
     */
    protected void requestCameraPermission(PermissionHandler permissionHandler) {
        this.mPermissionHandler = permissionHandler;
        BaseActivityPermissionsDispatcher.handleCameraPermissionWithCheck(this);
    }

    /**
     * 相机权限通过
     */
    @NeedsPermission({
            Manifest.permission.WRITE_EXTERNAL_STORAGE,
            Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.CALL_PHONE,
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.ACCESS_COARSE_LOCATION,
            Manifest.permission.RECORD_AUDIO})
    void handleCameraPermission() {
        // NOTE: Perform action that requires the permission. If this is run by PermissionsDispatcher, the permission will have been granted
        if (mPermissionHandler != null) {
            mPermissionHandler.onGranted();
        }
    }

    /***
     * 相机权限拒绝
     */
    @OnPermissionDenied({
            Manifest.permission.WRITE_EXTERNAL_STORAGE,
            Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.CALL_PHONE,
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.ACCESS_COARSE_LOCATION,
            Manifest.permission.RECORD_AUDIO})
    void deniedCameraPermission() {
        if (mPermissionHandler != null) {
            mPermissionHandler.onDenied();
        }
    }

    @OnNeverAskAgain({
            Manifest.permission.WRITE_EXTERNAL_STORAGE,
            Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.CALL_PHONE,
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.ACCESS_COARSE_LOCATION,
            Manifest.permission.RECORD_AUDIO})
    void OnCameraNeverAskAgain() {
        showDialog("[相机，电话，存储，位置，麦克风]");
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        BaseActivityPermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults);
    }

    public void showDialog(String permission) {
        new AlertDialog.Builder(this)
                .setTitle("权限申请")
                .setMessage("在设置-应用-" + getString(R.string.app_name) + "-权限中开启" + permission + "权限，以正常使用")
                .setPositiveButton("开启", (dialog, which) -> {
                    Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                    Uri uri = Uri.fromParts("package", getPackageName(), null);
                    intent.setData(uri);
                    startActivity(intent);
                    dialog.dismiss();
                })
                .setNegativeButton("取消", (dialog, which) -> {
                    if (mPermissionHandler != null) {
                        mPermissionHandler.onDenied();
                    }
                    dialog.dismiss();
                })
                .setCancelable(false)
                .show();
    }

    public boolean selfPermissionGranted(String permission) {
        // For Android < Android M, self permissions are always granted.
        boolean result = true;

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

            if (SystemUtils.getTargetSdkVersion(this) >= Build.VERSION_CODES.M) {
                // targetSdkVersion >= Android M, we can
                // use Context#checkSelfPermission
                result = checkSelfPermission(permission)
                        == PackageManager.PERMISSION_GRANTED;
            } else {
                // targetSdkVersion < Android M, we have to use PermissionChecker
                result = PermissionChecker.checkSelfPermission(this, permission)
                        == PermissionChecker.PERMISSION_GRANTED;
            }
        }
        System.out.println(permission + ":" + result);
        return result;
    }
}
